home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 …ember: Reference Library / Apple Developer Reference Library (December 1999) (Disk 1).iso / pc / technical documentation / develop / develop issue 26 / develop issue 26 code / truffles - display mgr. / sprocket / sources / sprocketmain.cp < prev    next >
Encoding:
Text File  |  1996-01-01  |  19.7 KB  |  774 lines

  1. /*
  2.     File:        SprocketMain.cp
  3.  
  4.     Contains:    The “guts” of a Macintosh application.
  5.  
  6.     Written by: Dave Falkenburg and many other SmartFriends™
  7.  
  8.     Copyright:    © 1993-1995 by Dave Falkenburg, all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.      
  12.         <17>     1/24/95    DRF        Added support for HandleMenuSelection. When building with GX
  13.                                     debugging on stop requiring a special hacked file by #including
  14.                                     the official C file here.
  15.         <16>     1/20/95    DRF        Use our own special version of GetNewMenuBar which should
  16.                                     automatically register menu commands found in CMNU resources.
  17.         <15>      1/3/95    DRF        Add Nitin’s changes for Drag handling: Call ClickAndDrag method
  18.                                     if the mouse starts moving after a click.
  19.         <14>      1/3/95    DRF        Overhauled menu handling: HandleMenuSelection is now part of Sprocket.
  20.                                     Added gMenuBar, a TMenuBar object which handles menu <-> menu
  21.                                     command mappings. Start calling AdjustMenusBeforeMenuSelection.
  22.         <13>     12/6/94    DRF        kUnresolvedSymbolAddress isn’t a Ptr in the latest universal
  23.                                     interfaces.
  24.         <12>    11/23/94    DRF        InstallAppleEventHandlers is now called InitAppleEventRoutines.
  25.         <11>    11/16/94    DRF        Added an explicit #include <Traps.h> for latest universal
  26.                                     headers. Also killed off a CFront warning.
  27.         <10>    11/12/94    DRF        Revised QuickDrawGX initialization based on changes made by Jon
  28.                                     Summer. We now use a 'gasz' resource to setup the size of the
  29.                                     graphics heap. Also we are now always TSM aware, not just when
  30.                                     TSMTE is around.
  31.          <9>     11/8/94    DRF        Rolled in LDR’s TSM fixes. Add fonts to the Fonts menu if it
  32.                                     exists. Also, stop openning up the preferences file here.
  33.          <8>     9/27/94    DRF         AppLib.h is now Sprocket.h, also fixed scrap coercion routines
  34.                                      and eliminated HandleUpdate.
  35.          <7>      9/9/94    DRF        Reordered headers and removed redundant #includes.
  36.                                     Conditionalized AOCE support. Also made changes to
  37.                                     TSMEventWrapper to be more like the code in InlineInputSample.
  38.          <6>      9/8/94    DRF        Add HiliteMenu(0) calls after calls to menu handling code
  39.                                     because TSMMenuSelect doesn’t do it. Also reorganized some GX
  40.                                     stuff: allocate and release a graphicsclient (Cam claims this
  41.                                     works on his machine), and turn on all the graphics errors and
  42.                                     notices if qDebug is set.
  43.          <5>      9/7/94    DRF        Rearrange YieldToAnyThread calls to make quitting faster.
  44.          <4>      9/4/94    DRF        Rearrange local variables in HandleMouseDown.
  45.          <3>      9/1/94    DRF        Stop including "MailableWindow.h" here.
  46.          <2>      9/1/94    DRF        More fixes for inline input, but we’re not really done yet.
  47.  */
  48.  
  49. #include "Sprocket.h"
  50.  
  51. #include <limits.h>        //    For LONG_MAX
  52.  
  53. #include <Fonts.h>
  54. #include <Desk.h>
  55. #include <GestaltEqu.h>
  56. #include <DiskInit.h>
  57. #include <Threads.h>
  58. #include <CodeFragments.h>    //    for kUnresolvedSymbolAddress
  59. #include <Traps.h>
  60.  
  61. #if    qInlineInputAware
  62. #include <TextServices.h>
  63. #include <TSMTE.h>
  64. #endif
  65.  
  66. #if    qUseQuickDrawGX
  67. #include <graphics macintosh.h>
  68. #include <graphics routines.h>
  69. #include <graphics libraries.h>
  70. #include <PrintingManager.h>
  71. #if    qUseQuickDrawGXDebugging
  72. #include <graphics debug library.c>
  73. #endif
  74. #endif
  75.  
  76. #include "StandardMenus.h"
  77. #include "Window.h"
  78. #include "SplashWindow.h"
  79. #include "AppleEventHandling.h"
  80.  
  81.  
  82. //    Function Prototypes
  83.  
  84. void    main(void);
  85. void    MainEventLoop(void);
  86.  
  87. void    HandleMouseDown(TWindow * topWindowObj, EventRecord * anEvent);
  88. void    HandleClose(WindowRef aWindow);
  89. void    HandleMenu(TWindow * topWindow, long menuCode);
  90.  
  91.  
  92. //    Globals
  93.  
  94. Boolean                gDone = false;
  95. TMenuBar *            gMenuBar = nil;
  96. TSplashWindow *        gSplashWindow = nil;
  97.  
  98. Boolean                gHasColorQuickdraw = false;
  99. Boolean                gHasThreadManager = false;
  100. Boolean                gHasDragManager = false;
  101. Boolean                gHasAppleScript = false;
  102. Boolean                gHasDisplayManager = false;
  103.  
  104. GrafPtr                gWindowManagerPort;
  105. Rect                gDeskRectangle;
  106. RgnHandle            gMouseRegion = nil;
  107.  
  108. short                gPreferencesRsrcRefNum;
  109.  
  110. #if    qAOCEAware
  111. Boolean                gHasAOCE = false;
  112. #endif
  113.  
  114. #if    qInlineInputAware
  115. Boolean                gHasTextServices = false;
  116. Boolean                gHasTSMTE = false;
  117.  
  118. Boolean                TSMEventWrapperForKotoeri(EventRecord *anEvent);
  119.  
  120. #endif
  121.  
  122. #if    qUseQuickDrawGX
  123. Boolean                gHasQuickDrawGX = false;
  124. long                gQuickDrawGXVersion = 0;
  125. long                gQuickDrawGXPrintingVersion = 0;
  126. gxGraphicsClient    gQuickDrawGXClient;
  127. #endif
  128.  
  129.  
  130. //    Values that can be adjusted by other application code to change
  131. //    the behavior of the MainEventLoop.
  132. //
  133. //    Rules of thumb:
  134. //
  135. //        Increase gXXXRunQuantum (and decrease gXXXSleepQuantum) when:
  136. //            The application has many threads running that need time
  137. //
  138. //        Decrease gXXXRunQuantum when:
  139. //            Sending AppleEvents to other applications
  140. //            Launching other applications
  141. //            Running in the background
  142.  
  143. unsigned long    gForegroundRunQuantum = 0;
  144. unsigned long    gForegroundSleepQuantum = GetCaretTime();
  145. unsigned long    gBackgroundRunQuantum = 0;
  146. unsigned long    gBackgroundSleepQuantum = LONG_MAX;
  147.  
  148.  
  149. //    Globals used to “tune” the performance of MainEventLoop
  150. //    (assume we’ll be starting in the foreground)
  151.  
  152. static    unsigned long    gRunQuantum = gForegroundRunQuantum;
  153. static    unsigned long    gSleepQuantum = gForegroundSleepQuantum;
  154.  
  155. #if GENERATINGPOWERPC
  156. #ifndef    __MWERKS__
  157. QDGlobals    qd;
  158. #endif
  159. #endif
  160.  
  161. void
  162. main(void)
  163.     {
  164.     long        feature;
  165.  
  166.     MaxApplZone();
  167.     MoreMasters();
  168.     MoreMasters();
  169.     MoreMasters();
  170.     MoreMasters();
  171.  
  172.     InitGraf(&qd.thePort);    
  173.     InitFonts();
  174.     InitWindows();
  175.     InitMenus();
  176.     TEInit();
  177.     InitDialogs(nil);
  178.  
  179.  
  180.     if (GetToolTrapAddress(_Unimplemented) == GetOSTrapAddress(_Gestalt))
  181.         FatalErrorAlert(kCoreErrorStrings,kUnsupportedSystemSoftware);
  182.  
  183.     if (Gestalt(gestaltQuickdrawFeatures,&feature) == noErr)
  184.         gHasColorQuickdraw = ((feature & (1 << gestaltHasColor)) != 0);
  185.  
  186.     gSplashWindow = new TSplashWindow;    
  187.  
  188.     //    Check for and Initialize QuickDraw GX early on to avoid heap fragmentation
  189.     
  190. #if    qUseQuickDrawGX
  191.     //    Check for and initialize QuickDrawGX
  192.     if (Gestalt(gestaltGXVersion, &gQuickDrawGXVersion) == noErr)
  193.         {
  194.         if (Gestalt(gestaltGXPrintingMgrVersion, &gQuickDrawGXPrintingVersion) == noErr)
  195.             {
  196. #if GENERATINGCFM
  197.             if ((Ptr) GXEnterGraphics != kUnresolvedSymbolAddress)
  198. #endif
  199.             gHasQuickDrawGX = true;
  200.             }
  201.         }
  202.  
  203.     if (gHasQuickDrawGX)
  204.         {
  205.         // Initialize the graphics and printing environments.
  206.         //    For additional details see "IM: QD GX Environment & Utilities."
  207.         
  208.         //    We let QuickDraw GX look for a resource  of type 'gasz' with an ID of 0.
  209.         //    GX uses the first long word of that resource as the graphics heap size.
  210.         //    To determine the memory requirements of your graphics client heap see:
  211.         //    “IM: QD GX Environment & Utilities pp2-8,2-9”
  212.         
  213.         //    NOTE:    If your application does not provide this resource,
  214.         //            QuickDraw GX version 1.0 uses a default size of 600 KB.
  215.  
  216.         gQuickDrawGXClient = GXNewGraphicsClient(nil, kUseGraphicsSizeResource, kAllowGXToExtendGraphicsHeap);
  217.         if (gQuickDrawGXClient)
  218.             {
  219.             //    NOTE:    GXNewGraphicsClient() does not allocate memory to the heap
  220.             //            until GXEnterGraphics()    is called, so go ahead and call it now
  221.             //            while we have a chance to deal with things nicely.
  222.             //
  223.             // NOTE:    GXEnterGraphics() should only fail if there is not enough memory. 
  224.             
  225.             GXEnterGraphics();
  226.  
  227.             if (GXGetGraphicsError(nil) == noErr)
  228.                 {
  229. #if    qUseQuickDrawGXDebugging
  230.                 // If qUseQuickDrawGXDebugging = TRUE, enable on GX Validation and graphics library errors & notices.
  231.  
  232.                 //    NOTES from Jon Summers:
  233.                 //    As you increase the amount of validation, drawing speed will SLOW
  234.                 //    down due to all of the internal checking. Also, if you play with
  235.                 //    settings enough validation seems to become inconsistent
  236.  
  237.                 GXSetValidation(    //    gxInternalValidation    |
  238.                                     //    gxAllObjectValidation    |
  239.                                     //    gxApHeapValidation        |
  240.                                         gxPublicValidation);        // check parameters to public routines
  241.  
  242.                 //    This functionality will only work with the "debugging" version of QuickDraw GX.
  243.                 //    If you don't have the debugging version installed, these functions will not work. 
  244.  
  245.                 SetGraphicsLibraryErrors();
  246.                 SetGraphicsLibraryNotices();    
  247. #endif
  248.                 if (GXInitPrinting() != noErr)        // See IM: QuickDraw GX Printing
  249.                     {
  250.                     //    We couldn’t initialize printing, so clean up pretend GX isn’t around
  251.                     //    ••• For safety’s sake, we’ll probably want to bail here.
  252.                     
  253.                     if (gQuickDrawGXClient)
  254.                         GXDisposeGraphicsClient(gQuickDrawGXClient);
  255.                     gHasQuickDrawGX = false;
  256.                     }
  257.                 }
  258.             }
  259.         }
  260.  
  261.     if (gQuickDrawGXClient)
  262.         InitCommonColors();        // Initialize the CommonColors Library.
  263. #if    qRequireQuickDrawGX
  264.     else
  265.         FatalErrorAlert(kCoreErrorStrings, kNeedsQuickdrawGX);
  266. #endif    //    qRequireQuickDrawGX
  267. #endif    //    qUseQuickDrawGX
  268.  
  269.  
  270.     if ((Gestalt(gestaltAppleEventsAttr,&feature) == noErr) &&
  271.         (feature & (1 << gestaltAppleEventsPresent)))
  272.         {
  273.         //    Figure out if we need to do AppleEvent recording
  274.         gHasAppleScript = ((feature & (1 << gestaltScriptingSupport)) != 0);
  275.         }
  276.     else
  277.         FatalErrorAlert(kCoreErrorStrings,kUnsupportedSystemSoftware);
  278.  
  279. #if    qInlineInputAware
  280.     if ((Gestalt(gestaltTSMgrVersion,&feature) == noErr) && (feature >= 1))
  281.         {
  282.         gHasTextServices = true;
  283.         if (Gestalt(gestaltTSMTEAttr, &feature) == noErr)
  284.             gHasTSMTE = (feature & (1 << gestaltTSMTEPresent));
  285.  
  286.         if (InitTSMAwareApplication() != noErr)
  287.             {
  288.             gHasTextServices = false;
  289.             gHasTSMTE = false;
  290.             }
  291.         }
  292.  
  293. #endif
  294.  
  295.     if (Gestalt(gestaltThreadMgrAttr,&feature) == noErr)
  296.         {
  297. #if GENERATINGCFM
  298.         //    If running on a PowerPC, make sure that we not only have the
  299.         //    68K Thread Manager, but also the PowerPC shared library, too.
  300.         //    Because of the wonders of weak linking and out of memory errors
  301.         //    we need to also check to make sure that an entrypoint in the library
  302.         //    is there, too. 
  303.         if ((Ptr) NewThread != (Ptr) kUnresolvedCFragSymbolAddress)
  304.             gHasThreadManager = ((feature & ((1 << gestaltThreadMgrPresent) | (1 << gestaltThreadsLibraryPresent))) != 0);
  305. #else
  306.         gHasThreadManager = ((feature & (1 << gestaltThreadMgrPresent)) != 0);
  307. #endif
  308.         }
  309.  
  310. #if    qRequireThreadManager
  311.     if (gHasThreadManager == false)
  312.         FatalErrorAlert(kCoreErrorStrings, kNeedsThreadManager);
  313. #endif
  314.  
  315.     //    Check for and install Drag Manager callbacks
  316.     if (Gestalt(gestaltDragMgrAttr,&feature) == noErr)
  317.         {
  318. #if GENERATINGCFM
  319.         //    If running on a PowerPC, make sure that we not only have the
  320.         //    68K Drag Manager, but also the PowerPC shared library, too.
  321.         if ((Ptr) NewDrag != (Ptr) kUnresolvedCFragSymbolAddress)
  322.             gHasDragManager = ((feature & ((1 << gestaltDragMgrPresent) | (1 << gestaltPPCDragLibPresent))) != 0);
  323. #else
  324.         gHasDragManager = ((feature & (1 << gestaltDragMgrPresent)) != 0);
  325. #endif
  326.  
  327.         if (gHasDragManager)
  328.             {
  329.             InstallTrackingHandler(NewDragTrackingHandlerProc(TWindow::CallDragTrackingHandler),(GrafPtr) nil,nil);
  330.             InstallReceiveHandler(NewDragReceiveHandlerProc(TWindow::CallDragReceiveHandler),(GrafPtr) nil,nil);
  331.             }
  332.         }
  333.  
  334.     //    Check for Display Manager
  335.     if (Gestalt(gestaltDisplayMgrAttr,&feature) == noErr)
  336.         gHasDisplayManager = ((feature & (1 << gestaltDisplayMgrPresent)) != 0);
  337.  
  338. #if    qAOCEAware    
  339.     //    Check for and initialize AOCE Standard Mail package if it exists
  340.     if ((Gestalt(gestaltSMPMailerVersion,&feature) == noErr) && (feature != 0))
  341.         {
  342. #if GENERATINGCFM
  343.         if ((Ptr) SMPInitMailer != kUnresolvedCFragSymbolAddress)
  344.             gHasAOCE = (SMPInitMailer(kSMPVersion) == noErr);
  345. #else
  346.         gHasAOCE = (SMPInitMailer(kSMPVersion) == noErr);
  347. #endif
  348.         }
  349. #endif
  350.  
  351.     //    Initialize our AppleEvent Handling Routines
  352.     InitAppleEventRoutines();
  353.  
  354.     //    Setup desktop rectangle for dragging windows around            
  355.     GetWMgrPort(&gWindowManagerPort);
  356.     gDeskRectangle = (**GetGrayRgn()).rgnBBox;
  357.  
  358.     //    Setup the default menubar
  359.     //        First, create a TMenuBar so we can register commands
  360.     gMenuBar = new TMenuBar();
  361.  
  362.     //        Add the Macintosh menus via an MBAR resource
  363.     gMenuBar->GetNewMenuBar(rMenuBar);
  364.     
  365.     //        add AppleMenu items
  366.     AppendResMenu(GetMenuHandle(mApple),'DRVR');
  367.  
  368.     //        …and add fonts to the font menu (if it is installed)
  369.     if (GetMenuHandle(mFont))
  370.         AppendResMenu(GetMenuHandle(mFont),'FONT');
  371.  
  372.     if (SetupApplication() == noErr)
  373.         {
  374.         delete gSplashWindow;    //    get rid of the splash screen
  375.         MainEventLoop();
  376.         TearDownApplication();
  377.         }
  378.  
  379. #if    qInlineInputAware
  380.     if (gHasTextServices)
  381.         (void) CloseTSMAwareApplication();
  382. #endif
  383.         
  384. #if    qUseQuickDrawGX
  385.     //    Tear down QuickDrawGX
  386.     if (gHasQuickDrawGX && gQuickDrawGXClient)
  387.         {
  388.         DisposeCommonColors();
  389.         GXExitPrinting();        // Close the new printing mgr. 
  390.         GXExitGraphics();        // Deallocate all of the default structures
  391.         GXDisposeGraphicsClient(gQuickDrawGXClient);    
  392.         }
  393. #endif
  394.     }
  395.  
  396.  
  397. void
  398. MainEventLoop(void)
  399.     {
  400.     EventRecord        anEvent;
  401.     unsigned long    nextTimeToCheckForEvents = 0;
  402.     
  403.     while (!gDone)
  404.         {
  405.         if (gHasThreadManager)
  406.             YieldToAnyThread();
  407.  
  408.         if ((gRunQuantum == 0) ||
  409.             (TickCount() > nextTimeToCheckForEvents))
  410.             {
  411.             nextTimeToCheckForEvents = TickCount() + gRunQuantum;
  412.             
  413.             (void) WaitNextEvent(everyEvent,&anEvent,gSleepQuantum,gMouseRegion);
  414.                         
  415. #if    qInlineInputAware
  416.             if (gHasTextServices && TSMEventWrapperForKotoeri(&anEvent))
  417.                 {
  418.                 }
  419.             else
  420. #endif
  421.                 HandleEvent(&anEvent);
  422.             }
  423.         }
  424.     }
  425.  
  426. #if    qInlineInputAware
  427.  
  428. Boolean
  429. TSMEventWrapperForKotoeri(EventRecord *anEvent)
  430.     {
  431.     short        oldFont;
  432.     ScriptCode    keyboardScript;
  433.     Boolean        didTSMHandleTheEvent = false;
  434.  
  435.     //    This snippet of code is from TE 27: Inline Input & TextEdit
  436.     //    and is related to working around a bug in Kotoeri, one of the
  437.     //    Japanese Input methods when operating in a mixed script
  438.     //    environment (e.g., Japanese Language Kit)
  439.     
  440.     // make sure we have a port and it's not the Window Manager port
  441.     if (qd.thePort != nil)
  442.         {
  443.         oldFont            = qd.thePort->txFont;
  444.         keyboardScript    = GetScriptManagerVariable(smKeyScript);
  445.  
  446.         if (FontToScript(oldFont) != keyboardScript)
  447.             TextFont(GetScriptVariable(keyboardScript, smScriptAppFond));
  448.         }
  449.  
  450.     didTSMHandleTheEvent = TSMEvent(anEvent);
  451.     
  452.     TextFont(oldFont);        //    restore the font, even though the sample code didn’t
  453.  
  454.     return didTSMHandleTheEvent;
  455.     }
  456.  
  457. #endif    
  458.  
  459.  
  460.  
  461. void
  462. HandleEvent(EventRecord *anEvent)
  463.     {
  464.     TWindow    * wobj;
  465.     
  466.     if (anEvent->what != updateEvt)
  467.         wobj = GetWindowObject(TWindow::FrontNonFloatingWindow());
  468.     else
  469.         wobj = GetWindowObject((WindowRef) anEvent->message);
  470.  
  471.     if (wobj != nil)
  472. #if    qInlineInputAware
  473.         // give text services a chance to set the cursor shape
  474.         if (gHasTextServices && SetTSMCursor(anEvent->where))
  475.             ;    // do nothing, TSM did it for me
  476.         else    
  477. #endif
  478.             wobj->AdjustCursor(anEvent);
  479.     
  480.     if ((wobj != nil) && wobj->EventFilter(anEvent))
  481.         return;
  482.         
  483.     else switch (anEvent->what)
  484.         {
  485.         case    nullEvent:
  486.             if (wobj != nil)
  487.                 wobj->Idle(anEvent);
  488.             break;
  489.             
  490.         case    mouseDown:
  491.             HandleMouseDown(wobj,anEvent);
  492.             break;
  493.         
  494.         case    keyDown:
  495.         case    autoKey:
  496.             if (anEvent->modifiers & cmdKey)
  497.                 {
  498.                 if (wobj != nil)
  499.                     wobj->AdjustMenusBeforeMenuSelection();
  500.  
  501.                 long    menuResult = MenuKey((short) anEvent->message & charCodeMask);
  502. #if    qInlineInputAware
  503.                 if (!(gHasTextServices && TSMMenuSelect(menuResult)))
  504. #endif
  505.                     HandleMenu(wobj,menuResult);
  506.                 if (wobj != nil)
  507.                     wobj->AdjustMenusAfterMenuSelection();
  508.                 HiliteMenu(0);
  509.                 }
  510.             else if (wobj != nil)
  511.                 wobj->KeyDown(anEvent);
  512.             break;
  513.             
  514.         case    updateEvt:
  515.             {
  516.             GrafPtr        oldPort;
  517.             WindowRef    aWindow = (WindowRef) anEvent->message;    
  518.                 
  519.             GetPort(&oldPort);
  520.             SetPortWindowPort(aWindow);
  521.             BeginUpdate(aWindow);
  522.             if (wobj != nil)
  523.                 wobj->Draw();
  524.             EndUpdate(aWindow);
  525.             SetPort(oldPort);
  526.             }
  527.             break;
  528.             
  529.         case diskEvt:
  530.             if (anEvent->message >> 16)
  531.                 {
  532.                 static    Point    where = {50,50};
  533.                 (void) DIBadMount(where,anEvent->message);
  534.                 }
  535.             break;
  536.                 
  537.         case    osEvt:
  538.             switch ((anEvent->message & osEvtMessageMask) >> 24)
  539.                 {
  540.                 case    mouseMovedMessage:
  541.                     break;
  542.                     
  543.                 case    suspendResumeMessage:                    
  544.  
  545.                     TWindow::SuspendResumeWindows((anEvent->message & resumeFlag) != 0);
  546.  
  547.                     if (anEvent->message & resumeFlag)
  548.                         {
  549.                         if (anEvent->message & convertClipboardFlag)
  550.                             ReadLocalClipboardFromScrap();
  551.  
  552.                         gRunQuantum = gForegroundRunQuantum;
  553.                         gSleepQuantum = gForegroundSleepQuantum;
  554.                         }
  555.                     else
  556.                         {
  557.                         if (anEvent->message & convertClipboardFlag)
  558.                             WriteLocalClipboardToScrap();
  559.                         gRunQuantum = gBackgroundRunQuantum;
  560.                         gSleepQuantum = gBackgroundSleepQuantum;
  561.                         }
  562.  
  563.                     break;
  564.                 }
  565.             break;
  566.         
  567.         case    kHighLevelEvent:
  568.             (void) AEProcessAppleEvent(anEvent);
  569.             break;
  570.             
  571.         default:
  572.             break;
  573.         }
  574.     }
  575.  
  576. void
  577. HandleMouseDown(TWindow * topWindowObj,EventRecord *anEvent)
  578.     {
  579.     WindowRef    aWindow;
  580.     TWindow        *wobj;
  581.     short        partCode;
  582.  
  583.     partCode = FindWindow(anEvent->where,&aWindow);
  584.     wobj = GetWindowObject(aWindow);
  585.     switch(partCode)
  586.         {
  587.         case    inMenuBar:
  588.             //    Thanks mclow! FindWindow made aWindow NULL when inMenuBar!
  589.             wobj = GetWindowObject(TWindow::FrontNonFloatingWindow());
  590.             if (wobj != nil)
  591.                 wobj->AdjustMenusBeforeMenuSelection();
  592.  
  593.             long    menuResult = MenuSelect(anEvent->where);
  594. #if    qInlineInputAware
  595.             if (!(gHasTextServices && TSMMenuSelect(menuResult)))
  596. #endif
  597.                 HandleMenu(topWindowObj,menuResult);
  598.             HiliteMenu(0);
  599.             break;
  600.             
  601.         case    inSysWindow:
  602.             SystemClick(anEvent, (GrafPtr) aWindow);
  603.             break;
  604.             
  605.         case    inContent:
  606.             if (wobj != nil)
  607.                 {
  608.                 GrafPtr    oldPort;
  609.                 
  610.                 GetPort(&oldPort);
  611.                 SetPortWindowPort(aWindow);
  612.                 GlobalToLocal(&anEvent->where);
  613.                 wobj->Click(anEvent);
  614.                 SetPortWindowPort(aWindow);
  615.                 }
  616.             break;
  617.             
  618.         case    inDrag:
  619.             if (wobj)
  620.                 wobj->Drag(anEvent->where);
  621.             break;
  622.             
  623.         case    inGrow:
  624.             if (wobj)
  625.                 wobj->Grow(anEvent->where);
  626.             break;
  627.             
  628.         case    inGoAway:
  629.             if (TrackGoAway(aWindow,anEvent->where))
  630.                 HandleClose(aWindow);
  631.             break;
  632.  
  633.         case    inZoomIn:
  634.         case    inZoomOut:
  635.             if (TrackBox(aWindow,anEvent->where,partCode) && (wobj))
  636.                 wobj->Zoom(partCode);
  637.             break;
  638.             
  639.         default:
  640.             break;
  641.         }
  642.     }
  643.     
  644.  
  645. void
  646. HandleClose(WindowRef aWindow)
  647.     {
  648.     short    windowKind;
  649.     TWindow    *wobj;
  650.     
  651.     if (aWindow)
  652.         {
  653.         windowKind = GetWindowKind(aWindow);
  654.         if (windowKind < 0)
  655.             {
  656.             CloseDeskAcc(GetWindowKind(aWindow));
  657.             }
  658.         else if ( ((wobj = GetWindowObject(aWindow)) != nil) &&
  659.                     wobj->CanClose() )
  660.             {
  661.             wobj->Close();
  662.             }
  663.         }
  664.     }
  665.  
  666. void
  667. HandleMenu(TWindow * topWindow, long menuCode)
  668.     {
  669.     short    menu = (short) (menuCode >> 16);
  670.     short    item = (short) (menuCode & 0xffff);
  671.                     
  672.     //    First, some special case menu handling for Mac OS:    
  673.     //        • Openning “Desk Accessories”
  674.     //        • Passing Edit commands through SystemEdit.
  675.  
  676. #if    !STRICT_MENUS
  677.     if (menuCode == 0)
  678.         {
  679.         //    Check for selecting a hierarchical menu’s parent item
  680.         
  681.         menuCode = MenuChoice();
  682.         if (menuCode != 0)
  683.             {
  684.             MenuHandle    theMenuHandle;
  685.             short        cmdChar;
  686.  
  687.             menu = (short) (menuCode >> 16);
  688.             item = (short) (menuCode & 0xffff);
  689.  
  690.             theMenuHandle = GetMenuHandle(menu);
  691.             if (theMenuHandle != NULL)
  692.                 {
  693.                 //    If it wasn’t a hierarchical menu parent, bail
  694.  
  695.                 GetItemCmd(theMenuHandle,item,&cmdChar);
  696.                 if (cmdChar != hMenuCmd)
  697.                     return;
  698.  
  699.                 //    If the item wasn’t enabled, bail
  700.         
  701.                 if (((**theMenuHandle).enableFlags & (1 << item)) == 0)
  702.                     return;
  703.                 }
  704.             else
  705.                 return;
  706.             }            
  707.         }
  708. #endif
  709.  
  710.     switch (menu)
  711.         {
  712.         case    mApple:
  713.             if (item != iAbout)
  714.                 {
  715.                 Str255    deskAccName;
  716.                 
  717.                 GetMenuItemText(GetMenuHandle(mApple),item,deskAccName);
  718.                 (void) OpenDeskAcc(deskAccName);
  719.                 return;
  720.                 }
  721.             break;
  722.         
  723.         case    mEdit:
  724.             if (SystemEdit(item-1))
  725.                 return;
  726.         
  727.         default:
  728.             break;
  729.         }
  730.  
  731.  
  732.     //    Next, check to see if the menu selection is a command
  733.  
  734.     MenuCommandID    command = gMenuBar->GetCommand(menu,item);
  735.  
  736.     if (command)
  737.         {
  738.         if (command == cQuit)
  739.             {
  740.             gDone = QuitApplication();
  741.             return;
  742.             }
  743.         else if (topWindow)
  744.             {
  745.             if (topWindow->DoMenuCommand(command))
  746.                 return;
  747.             }
  748.  
  749.         //    Nobody else wanted to handle the command, so let
  750.         //    the application get a crack at it.
  751.                 
  752.         HandleMenuCommand(command);
  753.         }
  754.     else
  755.         {
  756.         //    If we don’t have a command, give the active window a
  757.         //    chance to handle the raw menu selection.
  758.  
  759.         //    Windows which need to respond to dynamic menus (such as
  760.         //    Font or Windows) menus should use this method.
  761.         
  762.         if (topWindow)
  763.             {
  764.             if (topWindow->DoMenuSelection(menu,item))
  765.                 return;
  766.             }
  767.         
  768.         //    No window wanted to handle the selection, go ahead
  769.         //    and give the application a crack at it.
  770.         
  771.         HandleMenuSelection(menu,item);
  772.         }
  773.     }
  774.